﻿using System.Collections.Generic;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using SunRayEngine.Maps;
using System;

namespace SunRayEngine.MapEditor.EditTools
{
    public class MapTile
    {
        #region fields
        private Point offset;
        private Texture2D texture;
        private PixelInfo[,] pixels;
        private Rectangle bounds;
        private Rectangle transformedBounds;
        #endregion

        #region properties
        public Point Offset { get { return offset; } }
        public Rectangle Bounds { get { return transformedBounds; } }
        public PixelInfo[,] Pixels { get { return pixels; } }
        #endregion

        #region initialize
        public MapTile(int x, int y, int width, int height, GraphicsDevice device)
        {
            offset = Point.Zero;
            texture = new Texture2D(device, width, height, false, SurfaceFormat.Color);
            bounds = new Rectangle(x, y, width, height);
            transformedBounds = bounds;
            pixels = new PixelInfo[width, height];

            for (int i = 0; i < width; i++)
                for (int j = 0; j < height; j++)
                    pixels[i, j].Color = Color.White;

            pixelsToTexture();

        }
        #endregion

        #region methods
        public void EditOffset(Point p)
        {
            offset.X += p.X;
            offset.Y += p.Y;
            transformedBounds = new Rectangle(bounds.X + offset.X, bounds.Y + offset.Y, bounds.Width, bounds.Height);
        }

        public void PaintToTile(Brush brush, bool erase)
        {
            Color[] bTexCols = new Color[brush.PaintTexture.Width * brush.PaintTexture.Height];
            brush.PaintTexture.GetData<Color>(bTexCols);

            Point[] selPixels = selectedPixels(brush);

            foreach(var p in selPixels)
            {
                if (erase)
                {
                    pixels[p.Y, p.X].Color = Color.Lerp(pixels[p.Y, p.X].Color, Color.White, ((float)brush.Alpha / 100f));
                    continue;
                }

                if (bTexCols.Length != 1)
                {
                    Color c = bTexCols[p.X + brush.PaintTexture.Width * p.Y];

                    pixels[p.Y, p.X].Color = Color.Lerp(pixels[p.Y, p.X].Color, c, ((float)brush.Alpha / 100f));
                }
                else
                {
                    pixels[p.Y, p.X].Color = Color.Lerp(pixels[p.Y, p.X].Color, bTexCols[0], ((float)brush.Alpha / 100f));
                }
            }

            pixelsToTexture();
        }

        private Point[] selectedPixels(Brush brush)
        {
            List<Point> points = new List<Point>();

            Rectangle brushB = brush.GetBounds();
            Rectangle intersection = Rectangle.Intersect(transformedBounds, brushB);
            Rectangle result = new Rectangle(intersection.X - transformedBounds.X, intersection.Y - transformedBounds.Y,
                intersection.Width, intersection.Height);

            for(int x = result.X; x < transformedBounds.Width; x++)
                for (int y = result.Y; y < transformedBounds.Height; y++)
                    if (x >= 0 && x < result.Width + result.X &&
                        y >= 0 && y < result.Height + result.Y)
                    {
                        points.Add(new Point(x, y));
                    }

            return points.ToArray();
        }

        private void pixelsToTexture()
        {
            List<Color> colors = new List<Color>();
            for (int x = 0; x < bounds.Width; x++)
            {
                for (int y = 0; y < bounds.Height; y++)
                {
                    colors.Add(pixels[x, y].Color);
                }
            }

            texture.SetData<Color>(colors.ToArray());
        }

        public void EditInfo(PixelInfo[,] pixels)
        {
            this.pixels = pixels;
            pixelsToTexture();
        }

        public void Draw(SpriteBatch spriteBatch)
        {
            if(texture != null)
                spriteBatch.Draw(texture, transformedBounds, Color.White);
        }
        #endregion
    }
}
